#include "sphereIso.h"
#include "math.h"
#include "drawing.h"
#include "common.h"

#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "OpenGl\gl.h"
#include "OpenGl\glu.h"

namespace Tmpl {

Sphere::Sphere()
{
	mVertexCount = 0;
	mTriangleCount = 0;

	// Create the 12 vertices
	mVertices = MALLOC64(12, Vertex);
	mVertices[mVertexCount++] = Vertex(Vec3f(-0.0f, 1.0f, 0.0f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(0.8944f, 0.4472f, -0.0000f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(0.2764f, 0.4472f, -0.8507f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(-0.7236f, 0.4472f, -0.5257f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(-0.7236f, 0.4472f, 0.5257f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(0.2764f, 0.4472f, 0.8507f).Normalized());  
    mVertices[mVertexCount++] = Vertex(Vec3f(0.7236f, -0.4472f, 0.5257f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(0.7236f, -0.4472f, -0.5257f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(-0.2764f, -0.4472f, -0.8507f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(-0.8944f, -0.4472f, 0.0000f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(-0.2764f, -0.4472f, 0.8507f).Normalized());
    mVertices[mVertexCount++] = Vertex(Vec3f(0.0000f, -1.0000f, 0.0000f).Normalized());

	// Create the 20 triangles
	mTriangles = MALLOC64(20, Triangle);
	mTriangles[mTriangleCount++] = Triangle( 0, Vec2f(1,1), 1, Vec2f(0,1),  2, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 0, Vec2f(1,1), 2, Vec2f(0,1),  3, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 0, Vec2f(1,1), 3, Vec2f(0,1),  4, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 0, Vec2f(1,1), 4, Vec2f(0,1),  5, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 0, Vec2f(1,1), 5, Vec2f(0,1),  1, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 1, Vec2f(1,1), 6, Vec2f(0,1),  7, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 2, Vec2f(1,1), 7, Vec2f(0,1),  8, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 3, Vec2f(1,1), 8, Vec2f(0,1),  9, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 4, Vec2f(1,1), 9, Vec2f(0,1), 10, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 5, Vec2f(1,1),10, Vec2f(0,1),  6, Vec2f(1,0));
    mTriangles[mTriangleCount++] = Triangle( 7, Vec2f(0,0), 2, Vec2f(1,0),  1, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle( 8, Vec2f(0,0), 3, Vec2f(1,0),  2, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle( 9, Vec2f(0,0), 4, Vec2f(1,0),  3, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(10, Vec2f(0,0), 5, Vec2f(1,0),  4, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle( 6, Vec2f(0,0), 1, Vec2f(1,0),  5, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(11, Vec2f(0,0), 8, Vec2f(1,0),  7, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(11, Vec2f(0,0), 9, Vec2f(1,0),  8, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(11, Vec2f(0,0),10, Vec2f(1,0),  9, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(11, Vec2f(0,0), 6, Vec2f(1,0), 10, Vec2f(0,1));
	mTriangles[mTriangleCount++] = Triangle(11, Vec2f(0,0), 7, Vec2f(1,0),  6, Vec2f(0,1));
}

Vec2f Sphere::GetTextureCoord(const Vec3f& normal)
{
	/*
	float u;
	if (fabs(normal.z) < 0.0001f)
	{
		u = ((normal.x * PI) / 2);
	}
	else 
	{   
		u = atan(normal.x / normal.z);  
		if (normal.z < 0) u += PI;   
	}
	if (u < 0) u += 2 * PI;  
	float v = (float)atan(normal.y/normal.x);	
	return Vec2f(u,v);
	*/
	return Vec2f(0.5f * ( 1.0f + atan2( normal.z , normal.x ) * ( 1.0f / PI )), acos( normal.y ) * ( 1.0f / PI ));
}

void Sphere::SubDivide()
{
	int size = mTriangleCount;
	mVertices = REALLOC64(mVertices, mVertexCount + size * 3, Vertex);
	mTriangles = REALLOC64(mTriangles, mTriangleCount * 4, Triangle);
	for (int i=0; i<size; ++i)
	{
		Triangle& t = mTriangles[i];

		// uv coords
		Vec2f t0 = t.uv0;
		Vec2f t1 = t.uv1;
		Vec2f t2 = t.uv2;
		Vec2f t01 = (t.uv0 + t.uv1) * 0.5f;
		Vec2f t02 = (t.uv0 + t.uv2) * 0.5f;
		Vec2f t12 = (t.uv1 + t.uv2) * 0.5f;

		// Create the vertices
		int v01 = mVertexCount;
		mVertices[mVertexCount++] = Vertex((mVertices[t.v0].pos + mVertices[t.v1].pos).Normalized());
		int v02 = mVertexCount;
		mVertices[mVertexCount++] = Vertex((mVertices[t.v0].pos + mVertices[t.v2].pos).Normalized());
		int v12 = mVertexCount;
		mVertices[mVertexCount++] = Vertex((mVertices[t.v1].pos + mVertices[t.v2].pos).Normalized());
		int v0 = t.v0;
		int v1 = t.v1;
		int v2 = t.v2;

		// Create the 4 triangles
		mTriangles[mTriangleCount++] = Triangle(v0, t0, v01, t01, v02, t02);
		mTriangles[mTriangleCount++] = Triangle(v2, t2, v02, t02, v12, t12);
		mTriangles[mTriangleCount++] = Triangle(v1, t1, v12, t12, v01, t01);
		t = Triangle(v01, t01, v12, t12, v02, t02);
	}
}

static Image* tex = 0;
void Sphere::Render()
{     
	if (!tex)
	{
		tex = new Image();
		tex->Create("Data/grass.png");
		tex->BuildTex();
	}
	tex->BindTexture();

	// Render the Texture
	glBegin(GL_TRIANGLES);
	for (int i=0; i<mTriangleCount; ++i)
	{
		Triangle* t = &mTriangles[i];

		glTexCoord2fv(GetTextureCoord(mVertices[t->v0].pos));
		glVertex3fv(mVertices[t->v0].pos);

		glTexCoord2fv(GetTextureCoord(mVertices[t->v1].pos));
		glVertex3fv(mVertices[t->v1].pos);

		glTexCoord2fv(GetTextureCoord(mVertices[t->v2].pos));
		glVertex3fv(mVertices[t->v2].pos);
	}
	glEnd();

	/*
	// Render the UV
	glBegin(GL_TRIANGLES);
	for (int i=0; i<mTriangleCount; ++i)
	{
		Triangle* t = &mTriangles[i];

		glColor3f(t->uv0.x, t->uv0.y, 0);
		glVertex3f(t->v0->pos.x, t->v0->pos.y, t->v0->pos.z);

		glColor3f(t->uv1.x, t->uv1.y, 0);
		glVertex3f(t->v1->pos.x, t->v1->pos.y, t->v1->pos.z);

		glColor3f(t->uv2.x, t->uv2.y, 0);
		glVertex3f(t->v2->pos.x, t->v2->pos.y, t->v2->pos.z);
	}
	glEnd();
	*/

	/*
	// Render the Lines
	glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
	glColor3f(0,1,0);
	glBegin(GL_TRIANGLES);
	for (int i=0; i<mTriangleCount; ++i)
	{
		Triangle* t = &mTriangles[i];
		glVertex3f(t->v0->pos.x, t->v0->pos.y, t->v0->pos.z);
		glVertex3f(t->v1->pos.x, t->v1->pos.y, t->v1->pos.z);
		glVertex3f(t->v2->pos.x, t->v2->pos.y, t->v2->pos.z);
	}
	glEnd();
	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	glColor3f(1,1,1);
	*/

	/*
	// Render the Points
	glPointSize(10.0f);
	glBegin(GL_POINTS);
	for (int i=0; i<mVertexCount; ++i)
	{
		Vertex* v = &mVertices[i];
		glVertex3f(v->pos.x, v->pos.y, v->pos.z);
	}
	glEnd();
	glPointSize(1.0f);
	*/
}

}; // namespace Tmpl